/*
 * Copyright (c) 2009 Seth Wessitsh (seth@wessitsh.com)
 * Licensed under the MIT (MIT-LICENSE.txt) licence.
 */

var JSON = JSON ? JSON : {};
JSON.schema = JSON.schema ? JSON.schema : {};

JSON.schema.registry = {
	"string": {"id": "string", "extends": "any", "type": "string"},
	"object": {"id": "object", "extends": "any", "type": "object"},
	"array": {"id": "array", "extends": "any", "type": "array"},
	"boolean": {"id": "boolean", "extends": "any", "type": "boolean"},
	"number": {"id": "number", "extends": "any", "type": "number"},
	"integer": {"id": "integer", "extends": "number", "maxDecimal": 0},
	"null": {"id": "null", "extends": "any", "type": "null"},
	"any": {"id": "any", "type": "any"},
	"KnownSchemaName": {"type": "string", "enum": ["string", "object", "array", "boolean", "number", "integer", "null", "any", "KnownSchemaName", "JSONSchema"]},
	"JSONSchema": {"$ref": "http://json-schema.org/schema"},
	"JSONSchemas": { "type": "array", "items": {"type": "JSONSchema"} }
};
JSON.schema.registry.baseTypes = {
	"string": JSON.schema.registry.string,
	"object": JSON.schema.registry.object,
	"array": JSON.schema.registry.array,
	"boolean": JSON.schema.registry.boolean,
	"number": JSON.schema.registry.number,
	"null": JSON.schema.registry["null"],
	"any": JSON.schema.registry.any
};

JSON.schema.registry.register = function jsrRegister(schema, path) {
	path = path || "$";

	if (!(schema instanceof Array)) {
		schema = [schema];
	}

	for (var i in schema) {
		if (!schema.hasOwnProperty(i)) {
			continue;
		}

		if (
			schema[i].id && (this[schema[i].id] === undefined ||
			this[schema[i].id] === schema[i])
		) {
			this[schema[i].id] = schema[i];
		} else {
			if (schema[i].id) {
				throw new JSON.schema.err.InvalidValueError(
					"IVE001", {
						current: {
							schema: schema[i], 
							path: path + ".id", 
							value: schema[i].id
						},
						conflictsWith: {
							schema: JSON.schema.registry[schema[i].id],
							path: "JSON.schema.registry." + schema[i].id
						}
					}
				);
			} else {
				throw new JSON.schema.err.InvalidValueError(
					"IVE012", {
						current: {
							schema: schema[i], 
							path: path
						}
					}
				);
			}
		}
	}
};

JSON.schema.registry.unregister = function jsrUnregister(schema, path) {
	var i;
	path = path || "$";

	if (schema == "*") {
		for (i in this) {
			if (this.hasOwnProperty(i) && !(i in this.unregister.toKeep)) {
				delete this[i];
			}
		}
		return;
	}
	
	if (!(schema instanceof Array)) {
		schema = [schema];
	}

	for (i in schema) {
		if (!schema.hasOwnProperty(i)) {
			continue;
		}

		if (typeof(schema[i]) == "string") {
			if (!(schema[i] in this.unregister.toKeep)) {
				delete this[schema[i]];
			}
		} else if (
			schema[i].id && this[schema[i].id] !== undefined &&
			this[schema[i].id] === schema[i] && 
			!(schema[i].id in this.unregister.toKeep)
		) {
			delete this[schema[i].id];
		} else {
			if (schema[i].id) {
				throw new JSON.schema.err.InvalidValueError(
					"IVE001", {
						current: {
							schema: schema[i], 
							path: path + ".id", 
							value: schema[i].id
						},
						conflictsWith: {
							schema: JSON.schema.registry[schema[i].id],
							path: "JSON.schema.registry." + schema[i].id
						}
					}
				);
			} else {
				throw new JSON.schema.err.InvalidValueError(
					"IVE012", {
						current: {
							schema: schema[i], 
							path: path
						}
					}
				);
			}
		}
	}
};

JSON.schema.registry.unregister.toKeep = {"string":1, "object":1, "array":1, "boolean":1, "number":1, "integer":1, "null":1, "any":1, "KnownSchemaName":1, "JSONSchema":1, "JSONSchemas":1, "register":1, "unregister":1, "baseTypes":1};